package com.handle.system.svc.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.util.BeanUtil;
import com.handle.common.core.constants.ConstantEnums;
import com.handle.common.core.dto.token.User;
import com.handle.common.core.result.JsonResult;
import com.handle.common.core.utils.ContextHolderUtils;
import com.handle.common.core.utils.StringUtils;
import com.handle.system.api.constants.ResponseEnum;
import com.handle.system.api.dto.SysMenuDto;
import com.handle.system.api.entity.SysMenu;
import com.handle.system.api.entity.SysRoleDept;
import com.handle.system.api.request.menu.MenuAddOrEditParam;
import com.handle.system.api.request.menu.MenuQueryParam;
import com.handle.system.api.service.ISysMenuService;
import com.handle.system.svc.mapper.SysMenuMapper;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统菜单表 服务实现类
 * </p>
 *
 * @author zhangqing
 * @since 2021-03-13
 */
@Service
@AllArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    private final SysMenuMapper menuMapper;

    @Override
    public List<SysMenu> selectMenusByUser(User userDto) {
        List<SysMenu> menus;
        // 如果当前登录用户是租户管理员只能查看,除超级管理员才能看的页面的所有
        if(ContextHolderUtils.isSuperAdmin(userDto)){
            menus =  menuMapper.findMenuAll(userDto.getTenantCode());
        }else {
           menus = menuMapper.findMenusByUserId(userDto.getUserId());
        }
        return menus;
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectPermsByUserId(Long userId) {
        List<String> perms = menuMapper.findPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public List<Long> findMenuByRoleId(Long roleId) {
        List<SysMenu> allRoleMenu = menuMapper.findAllRoleMenu(roleId);
        return Optional.ofNullable(allRoleMenu).map(sysMenus -> sysMenus.stream().map(SysMenu::getId).collect(Collectors.toList())).orElse(null);
    }

    @Override
    public List<Tree<String>> findAllMenu() {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getStatus, ConstantEnums.MenuStatus.VISIBLE.getCode());
        List<SysMenu> sysMenus = menuMapper.selectList(lambda);
        // 初始化树形配置类
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig()
                .setIdKey("id")
                .setNameKey("name")
                .setWeightKey("orderNum")
                .setParentIdKey("parentId");
        //转换器
        return TreeUtil.build(sysMenus, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    tree.setWeight(treeNode.getOrderNum());
                    tree.setName(treeNode.getName());
                    if(!ConstantEnums.MenuType.METHODS.getCode().equals(treeNode.getMenuType())){
                        if(treeNode.getIsSuperAdminRead()){
                            tree.putExtra("disabled", treeNode.getIsSuperAdminRead());
                        }
                    }
                });
    }

    @Override
    public List<SysMenu> findMenuAndPermissionList() {
        return menuMapper.selectList(Wrappers.emptyWrapper());
    }

    @Override
    public List<SysMenu> findMenuList(MenuQueryParam menuQueryParam) {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(!StringUtils.isEmpty(menuQueryParam.getMenuName()),SysMenu::getName, menuQueryParam.getMenuName())
                .eq(!StringUtils.isEmpty(menuQueryParam.getStatus()),SysMenu::getStatus,menuQueryParam.getStatus());
        return menuMapper.selectList(lambda);
    }

    @Override
    public int addMenu(MenuAddOrEditParam menuAddOrEditParam) {
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(menuAddOrEditParam,sysMenu);
        if(menuAddOrEditParam.getOutsideTheChain()){
            sysMenu.setTarget("_blank");
            sysMenu.setPath(menuAddOrEditParam.getComponent());
            sysMenu.setComponent(null);
        }
        return menuMapper.insert(sysMenu);
    }

    @Override
    public JsonResult editMenu(MenuAddOrEditParam menuAddOrEditParam) {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getId, menuAddOrEditParam.getId());
        SysMenu sysMenu = menuMapper.selectOne(lambda);
        ResponseEnum.MENU_NOT_EXISTS.assertIsEmpty(sysMenu);
        BeanUtils.copyProperties(menuAddOrEditParam,sysMenu);
        return JsonResult.toJsonResult(menuMapper.updateById(sysMenu));
    }

    @Override
    public Boolean checkMenuName(String menuName,String menuId) {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getName, menuName);
        if(!StringUtils.isEmpty(menuId)){
            lambda.ne(SysMenu::getId,menuId);
        }
        List<SysMenu> sysMenus = menuMapper.selectList(lambda);
        return !sysMenus.isEmpty();
    }

    @Override
    public Boolean checkMenuKey(String menuKey, String menuId) {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getKey, menuKey);
        if(!StringUtils.isEmpty(menuId)){
            lambda.ne(SysMenu::getId,menuId);
        }
        List<SysMenu> sysMenus = menuMapper.selectList(lambda);
        return !sysMenus.isEmpty();
    }

    @Override
    public int delMenu(Long menuId) {
        // 查询该菜单是否存在
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getId, menuId);
        SysMenu sysMenu = menuMapper.selectOne(lambda);
        ResponseEnum.MENU_NOT_EXISTS.assertIsEmpty(sysMenu);
        // 如果存在获取菜单类型，删除子目录或菜单
        String menuChild = menuMapper.getMenuChild(menuId);
        List<Long> menuChildIds = Arrays.stream(menuChild.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        menuChildIds.add(menuId);
        List<Long> collect = menuChildIds.stream().distinct().collect(Collectors.toList());
        return menuMapper.batchDelMenu(collect);
    }

    @Override
    public JsonResult findMenuDetails(Long menuId) {
        LambdaQueryWrapper<SysMenu> lambda = new QueryWrapper<SysMenu>().lambda()
                .eq(SysMenu::getId, menuId);
        SysMenu sysMenu = menuMapper.selectOne(lambda);
        ResponseEnum.MENU_NOT_EXISTS.assertIsEmpty(sysMenu);
        return JsonResult.success(sysMenu);
    }
}
